using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UnityEngine;

public class Stat
{
    private float _baseValue;

    public float BaseValue
    {
        get => _baseValue;
        set
        {
            if (!Mathf.Approximately(_baseValue, value))
            {
                _baseValue = value;
                CalculateFinalValue();
            }
        }
    }

    public float Value { get; private set; }

    private readonly List<StatModifier> _modifiers = new();
    public ReadOnlyCollection<StatModifier> Modifiers => _modifiers.AsReadOnly();

    public event Action OnChange;

    public Stat(float baseValue)
    {
        Value = _baseValue = baseValue;
    }

    public bool HasModifier(StatModifier mod)
    {
        return _modifiers.Contains(mod);
    }

    public void AddModifier(StatModifier mod)
    {
        _modifiers.Add(mod);
        CalculateFinalValue();
    }

    public bool RemoveModifier(StatModifier mod)
    {
        if (_modifiers.Remove(mod))
        {
            CalculateFinalValue();
            return true;
        }

        return false;
    }

    public bool RemoveAllModifiersFromSource(object source)
    {
        if (_modifiers.RemoveAll(mod => mod.Source == source) > 0)
        {
            CalculateFinalValue();
            return true;
        }

        return false;
    }

    private void CalculateFinalValue()
    {
        var sumPercent = 0f;

        foreach (var mod in _modifiers)
        {
            if (mod.Type == StatModifierType.Percent)
            {
                sumPercent += mod.Value;
            }
        }

        Value = BaseValue * (1f + sumPercent / 100f);

        OnChange?.Invoke();
    }

    public static implicit operator float(Stat stat)
    {
        return stat.Value;
    }

    public override string ToString()
    {
        return $"{Value}";
    }
}